#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Ford UK NGc2 爬虫导航模块
包含页面导航、状态验证、Cookie处理等功能
"""

import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException


class NavigationHandler:
    """导航处理器，负责页面间的导航和状态验证"""
    
    def __init__(self, driver, wait):
        """
        初始化导航处理器
        
        Args:
            driver: WebDriver实例
            wait: WebDriverWait实例
        """
        self.driver = driver
        self.wait = wait
    
    def get_navigation_state(self):
        """
        获取当前导航状态
        
        Returns:
            dict: 导航状态信息，每个导航项包含enabled、aria_disabled、current等状态
        """
        try:
            nav_state = {}
            
            # 查找导航容器
            nav_container = self.driver.find_element(By.CSS_SELECTOR, 'nav[data-testid="Navigation_Container"]')
            
            # 查找所有导航项
            nav_items = nav_container.find_elements(By.CSS_SELECTOR, 'li, a, button')
            
            for item in nav_items:
                # 提取导航项文本
                item_text = item.text.strip()
                if not item_text:
                    continue
                
                # 获取状态信息
                aria_disabled = item.get_attribute('aria-disabled')
                is_current = item.get_attribute('aria-current') == 'step'
                is_enabled = not (aria_disabled == 'true')
                
                nav_state[item_text] = {
                    'enabled': is_enabled,
                    'aria_disabled': aria_disabled,
                    'current': is_current,
                    'element': item
                }
            
            return nav_state
            
        except Exception as e:
            print(f"获取导航状态时出错: {e}")
            return {}
    
    def find_navigation_button(self, nav_text):
        """
        查找导航栏中的指定按钮
        
        Args:
            nav_text (str): 导航按钮文本
            
        Returns:
            WebElement or None: 找到的导航按钮元素
        """
        try:
            # 尝试多种选择器查找导航按钮
            selectors = [
                f'nav a[href*="{nav_text.lower()}"]',
                f'nav button:contains("{nav_text}")',
                f'nav *[data-testid*="{nav_text}"]',
                f'nav li:contains("{nav_text}")',
            ]
            
            for selector in selectors:
                try:
                    elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for element in elements:
                        if nav_text.lower() in element.text.lower():
                            return element
                except Exception:
                    continue
            
            # 如果上述方法都失败，尝试通过XPath查找
            xpath_selectors = [
                f"//nav//a[contains(text(), '{nav_text}')]",
                f"//nav//button[contains(text(), '{nav_text}')]",
                f"//nav//li[contains(text(), '{nav_text}')]//a",
                f"//nav//li[contains(text(), '{nav_text}')]//button"
            ]
            
            for xpath in xpath_selectors:
                try:
                    element = self.driver.find_element(By.XPATH, xpath)
                    if element.is_displayed():
                        return element
                except Exception:
                    continue
            
            return None
            
        except Exception as e:
            print(f"查找导航按钮 '{nav_text}' 时出错: {e}")
            return None
    
    def verify_configuration_entry(self):
        """
        验证是否成功进入配置流程
        
        Returns:
            bool: 是否成功进入配置流程
        """
        try:
            # 检查方法1：查找Ford配置导航的特征文本
            nav_elements = self.driver.find_elements(By.CSS_SELECTOR, '[data-testid*="Navigation"], nav')
            ford_config_nav_found = False
            
            for nav_element in nav_elements:
                nav_text = nav_element.text.strip()
                # Ford配置页面的特征：包含Model, Drive, Bodystyle, Colour等关键词
                ford_config_keywords = ['Model', 'Drive', 'Bodystyle', 'Colour', 'Interior', 'Extras', 'Summary']
                
                if nav_text and len([keyword for keyword in ford_config_keywords if keyword in nav_text]) >= 4:
                    ford_config_nav_found = True
                    print(f"    ✅ 检测到Ford配置导航: {nav_text}")
                    break
            
            # 检查方法2：URL是否包含配置相关内容  
            current_url = self.driver.current_url.lower()
            config_indicators = ['configure', 'build', 'customize', 'config', 'ngc2', 'model']
            url_has_config = any(indicator in current_url for indicator in config_indicators)
            
            # 检查方法3：导航栏状态变化
            nav_state = self.get_navigation_state()
            has_nav_steps = len(nav_state) > 1
            
            # 综合判断 - 放宽条件，优先检测Ford特有的导航
            is_in_config = ford_config_nav_found or url_has_config or has_nav_steps
            
            if is_in_config:
                print("    ✅ 已成功进入配置流程")
                print(f"      - Ford配置导航: {ford_config_nav_found}")
                print(f"      - URL配置标识: {url_has_config}")
                print(f"      - 导航步骤数: {len(nav_state)}")
            else:
                print("    ❌ 未进入配置流程")
                print(f"      - 当前URL: {current_url}")
                print(f"      - 导航状态: {nav_state}")
            
            return is_in_config
            
        except Exception as e:
            print(f"验证配置流程进入状态时出错: {e}")
            return False


class CookieHandler:
    """Cookie处理器，负责处理网站的Cookie同意弹窗"""
    
    def __init__(self, driver, wait):
        """
        初始化Cookie处理器
        
        Args:
            driver: WebDriver实例
            wait: WebDriverWait实例
        """
        self.driver = driver
        self.wait = wait
    
    def handle_cookie_consent(self):
        """处理Cookie同意弹窗 - 增强版多重策略"""
        print("  🍪 处理Cookie同意弹窗...")
        
        try:
            # 等待更长时间让页面充分加载（基于福特网站的特点）
            time.sleep(8)  # 从5秒增加到8秒
            
            # 多重策略处理Cookie弹窗
            consent_handled = False
            
            # 策略1：福特特定的Cookie处理
            consent_handled = self.handle_ford_specific_cookies()
            
            if not consent_handled:
                # 策略2：通用Cookie处理
                consent_handled = self.handle_generic_cookies()
            
            if not consent_handled:
                # 策略3：强制清理Cookie元素
                self.force_cleanup_cookie_elements()
            
            # 最终等待让页面稳定
            time.sleep(3)
            
        except Exception as e:
            print(f"  ⚠️  处理Cookie时出现异常: {e}")
    
    def handle_ford_specific_cookies(self):
        """处理福特特定的Cookie弹窗"""
        print("    🎯 尝试福特特定Cookie处理...")
        
        # 福特网站的特定Cookie选择器
        ford_cookie_selectors = [
            'button[class*="CookieDisclaimer"][class*="Accept"]',
            'button[data-testid*="cookie"][data-testid*="accept"]',
            '.styles__CookieDisclaimerWrapper-sc-dx4a8y-0 button',
            'div[class*="CookieDisclaimer"] button[class*="Accept"]'
        ]
        
        for selector in ford_cookie_selectors:
            try:
                buttons = self.driver.find_elements(By.CSS_SELECTOR, selector)
                
                for button in buttons:
                    if button.is_displayed() and self.is_consent_button(button):
                        print(f"    ✓ 找到福特Cookie同意按钮: {selector}")
                        button.click()
                        time.sleep(2)
                        
                        # 验证Cookie弹窗是否消失
                        if not button.is_displayed():
                            print("    ✅ 福特Cookie弹窗已成功处理")
                            return True
                        
            except Exception as e:
                print(f"    福特Cookie选择器 {selector} 失败: {e}")
                continue
        
        return False
    
    def handle_generic_cookies(self):
        """处理通用Cookie弹窗"""
        print("    🔧 尝试通用Cookie处理...")
        
        # 通用Cookie按钮选择器
        generic_selectors = [
            'button[id*="accept"]',
            'button[class*="accept"]',
            'button[data-*="accept"]',
            'a[class*="accept"]',
            'button:contains("Accept")',
            'button:contains("同意")',
            'button:contains("Agree")',
            '[role="button"]:contains("Accept")'
        ]
        
        for selector in generic_selectors:
            try:
                elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                
                for element in elements:
                    if element.is_displayed() and self.is_consent_button(element):
                        print(f"    ✓ 找到通用Cookie同意按钮: {selector}")
                        element.click()
                        time.sleep(2)
                        return True
                        
            except Exception:
                continue
        
        return False
    
    def force_cleanup_cookie_elements(self):
        """强制清理Cookie相关元素"""
        print("    🗑️  强制清理Cookie元素...")
        
        try:
            cleanup_script = """
            // 查找并隐藏所有可能的Cookie弹窗
            var cookieElements = document.querySelectorAll(
                '[class*="cookie"], [id*="cookie"], [data-testid*="cookie"], ' +
                '[class*="Cookie"], [class*="consent"], [class*="Consent"], ' +
                '.modal, .overlay, [role="dialog"]'
            );
            
            var hiddenCount = 0;
            cookieElements.forEach(function(el) {
                try {
                    if (el.style.display !== 'none') {
                        el.style.display = 'none';
                        el.style.visibility = 'hidden';
                        el.style.opacity = '0';
                        el.style.pointerEvents = 'none';
                        hiddenCount++;
                    }
                } catch (e) {
                    // 忽略错误，继续处理下一个元素
                }
            });
            
            // 恢复页面滚动
            document.body.style.overflow = 'auto';
            
            return hiddenCount;
            """
            
            hidden_count = self.driver.execute_script(cleanup_script)
            if hidden_count > 0:
                print(f"    ✓ 强制隐藏了 {hidden_count} 个潜在Cookie元素")
            
        except Exception as e:
            print(f"    强制清理Cookie元素时出错: {e}")
    
    def is_consent_button(self, button):
        """
        判断按钮是否为Cookie同意按钮
        
        Args:
            button (WebElement): 按钮元素
            
        Returns:
            bool: 是否为同意按钮
        """
        try:
            button_text = button.text.lower()
            button_class = button.get_attribute('class') or ''
            button_id = button.get_attribute('id') or ''
            button_aria_label = button.get_attribute('aria-label') or ''
            
            # 同意关键词
            consent_keywords = [
                'accept', 'agree', 'ok', 'yes', 'allow', '同意', '接受', '确定'
            ]
            
            # 拒绝关键词
            reject_keywords = [
                'reject', 'deny', 'no', 'cancel', 'decline', '拒绝', '取消', '不同意'
            ]
            
            # 检查是否包含同意关键词
            has_consent = any(keyword in button_text or keyword in button_class or keyword in button_id or keyword in button_aria_label 
                             for keyword in consent_keywords)
            has_reject = any(keyword in button_text or keyword in button_class or keyword in button_aria_label 
                           for keyword in reject_keywords)
            
            return has_consent and not has_reject
            
        except Exception:
            return False